# /app.py
#!/usr/bin/env python
# encoding: utf-8
from flask import Flask, render_template, redirect, request, jsonify, Response, make_response
from flask_script import Manager, Shell
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, SQLAlchemySessionUserDatastore, \
    UserMixin, RoleMixin, login_required, auth_token_required, http_auth_required
from flask_cors import *

import json

app = Flask(__name__)
CORS(app, supports_credentials = True)

app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SECURITY_TRACKABLE'] = True
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_SEND_REGISTER_EMAIL'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///./dev.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False


# Create database connection object
db = SQLAlchemy(app)

# Define models
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))

    def __repr__(self):
        return '%r' % self.name

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    last_login_at = db.Column(db.DateTime())
    current_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(db.String(63))
    current_login_ip = db.Column(db.String(63))
    login_count = db.Column(db.Integer)
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

    def __repr__(self):
        return '<User %r>' % self.email

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)

# Create a user to test with
@app.before_first_request
def create_user():
    print("create user")
    db.create_all()
    if not User.query.first():
        user_datastore.create_role(name="user")
        user_datastore.create_role(name="admin")
        user_datastore.create_role(name="super_admin")
        user_datastore.create_user(email='a', password='a')
        #user_datastore.add_role_to_user('a', 'admin')
        user_datastore.add_role_to_user('a', 'super_admin')
        user_datastore.create_user(email='b', password='b')
        user_datastore.add_role_to_user('b', 'admin')
        user_datastore.create_user(email='c', password='c')
        user_datastore.add_role_to_user('c', 'user')
        db.session.commit()

# Views
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/__webpack_hmr')
def npm():
    return redirect('http://0.0.0.0:8080/__webpack_hmr')

@app.route('/home')
@login_required
def home():
    return 'you\'re logged in!'

@app.route('/new_login', methods=['POST'])
def login():
    req_data = json.loads(request.get_data())
    print('req_data:', req_data, ' ', type(req_data))
    user = User.query.filter_by(email=req_data['username'], password=req_data['password']).first()
    if user != None:
        roles_arr = list()
        for item in user.roles:
            roles_arr.append(item.name)
        print('email:', user.email, ' roles:', user.roles, 'token:', user.get_auth_token())
        print(type(user.roles))
        resp = make_response(jsonify({"err_code": 0, "res": { "email": user.email,
            "roles": roles_arr, 'token': user.get_auth_token()}}))
        return resp, 200
    return make_response(jsonify({"err_code": -1, "res": "no data"})), 200


@app.route('/api')
#@http_auth_required
@auth_token_required
def token_protected():
    return 'you\'re logged in by Token!'

if __name__ == '__main__':
    app.run()
